﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Medianamik.Core;
using Medianamik.Core.Sugar;
using Medianamik.UI.Controls;
using Telerik.Web.UI;
using Image = System.Drawing.Image;

namespace Medianamik.UI
{
    public static class Extensions
    {
        /// <summary>
        /// Searches recursively in this control to find a control with the name specified.
        /// </summary>
        /// <param name="root">The Control in which to begin searching.</param>
        /// <param name="id">The ID of the control to be found.</param>
        /// <returns>The control if it is found or null if it is not.</returns>
        public static Control FindControlR(this Control root, string id)
        {
            if (root != null)
            {
                var controlFound = root.FindControl(id);
                if (controlFound != null)
                {
                    return controlFound;
                }
                foreach (Control c in root.Controls)
                {
                    controlFound = c.FindControlR(id);
                    if (controlFound != null)
                    {
                        return controlFound;
                    }
                }
            }
            return null;
        }

        public static IEnumerable<T> FindControlsR<T>(this Control root)
        {
            if (root != null)
            {
                foreach (Control c in root.Controls)
                {
                    if (c is T) { yield return (T)(object)c; }
                    foreach (T item in FindControlsR<T>(c))
                    {
                        yield return item;
                    }
                }
            }
        }


        public static  T FindParentControlR<T>(this Control child)
            where T : class
        {
            var parent = child.Parent;

            while (parent != null)
            {
                if (parent is T)
                    return parent as T;

                parent = parent.Parent;
            }

            return null;
        }
        

        public static IEnumerable<Control> AllChildren(this Control root)
        {
            if (root == null)
            {
                throw new ArgumentNullException("root");
            }

            var rootResult = root.Controls.Cast<Control>();
            var childrenResult = rootResult.SelectMany(c => AllChildren(c));

            return rootResult.Concat(childrenResult);
        }

        public static TreeItem ToTreeItem<T>(this T node, string cultureName)
            where T : Node
        {
            CultureInfo cultureInfo = null;

            if (StringHelper.IsCulture(cultureName, ref cultureInfo))
            {
                node.DefaultCulture = cultureInfo;
            }

            return new TreeItem(node.Name, node.ID.ToString(), null, node.NodeType.IconPath,
                node.HasChildren);
        }

        public static RadTreeNode ToRadTreeNode<T>(this T node, string cultureName,
            TreeNodeExpandMode expandMode)
            where T : Node
        {
            CultureInfo cultureInfo = null;

            if (StringHelper.IsCulture(cultureName, ref cultureInfo))
            {
                node.DefaultCulture = cultureInfo;
            }

            var treeNode = new RadTreeNode(node.Name, node.ID.ToString());

            if (!string.IsNullOrEmpty(node.NodeType.IconPath))
            {
                treeNode.ImageUrl = node.NodeType.IconPath;
            }

            treeNode.ExpandMode = node.HasChildren ? expandMode : TreeNodeExpandMode.ClientSide;

            return treeNode;
        }

        public static RadTreeNodeData ToRadTreeNodeData<T>(this T node, string cultureName)
            where T : Node
        {
            CultureInfo cultureInfo = null;

            if (StringHelper.IsCulture(cultureName, ref cultureInfo))
            {
                node.DefaultCulture = cultureInfo;
            }

            return new RadTreeNodeData
                       {
                            Text = node.Name,
                            Value = node.ID.ToString(),
                            ExpandMode = node.HasChildren ? TreeNodeExpandMode.WebService : TreeNodeExpandMode.ClientSide,
                            ImageUrl = node.NodeType.IconPath,
                            Attributes = new Dictionary<String, object>
                                 { 
                                    { "CultureName", cultureName},
                                    {"Secured", node.IsSecured},
                                    {"SpecificallySecured", node.Permissions.Count > 0} 
                                 }
                        };
        }

        /// <summary>
        /// Sorts a RadTreeNodeCollection by text, in alphabetical order
        /// </summary>
        /// <param name="nodes">The RadTreeNodeCollection to be sorted</param>
        public static void Sort(this RadTreeNodeCollection nodes)
        {
            Sort(nodes, (n1, n2) => n1.Text.CompareTo(n2.Text));
        }

        /// <summary>
        /// Sorts a RadTreeNodeCollection using a comparison expression
        /// </summary>
        /// <param name="nodes">The RadTreeNodeCollection to be sorted</param>
        /// <param name="comp">The comparison expression used to sort the collection</param>
        public static void Sort(this RadTreeNodeCollection nodes, Comparison<RadTreeNode> comp)
        {
            var sortedNodes = nodes.Cast<RadTreeNode>().ToList();
            sortedNodes.Sort(comp);
            nodes.Clear();
            nodes.AddRange(sortedNodes);
        }

        public static void SendFile(this HttpResponse response, string filename)
        {
            if (!File.Exists(filename)) return;

            var fs = new FileStream(filename, FileMode.Open, FileAccess.Read);

            var bytBytes = new byte[fs.Length];

            fs.Read(bytBytes, 0, (int)fs.Length);
            fs.Close();

            //S'assurer que le navigateur détecte bien que c'est un pdf
            response.AddHeader("Content-disposition", "attachment; filename=" + Path.GetFileName(filename));
            response.ContentType = "application/octet-stream";
            response.BinaryWrite(bytBytes);

            response.End();
        }

        public static Image ResizeImageWithMaxDimensions(this Image imgPhoto, int maxWidth, int maxHeight)
        {
            var sourceWidth = imgPhoto.Width;
            var sourceHeight = imgPhoto.Height;
            var destWidth = sourceWidth;
            var destHeight = sourceHeight;
            const int sourceX = 0;
            const int sourceY = 0;
            const int destX = -1;
            const int destY = -1;

            do
            {
                float nPercent;

                if (destWidth > maxWidth)
                    nPercent = ((float)maxWidth / (float)destWidth);
                else
                    nPercent = ((float)maxHeight / (float)destHeight);

                destWidth = (int)(destWidth * nPercent);
                destHeight = (int)(destHeight * nPercent);
            } while (destWidth > maxWidth || destHeight > maxHeight);

            var bmPhoto = new Bitmap(destWidth,
                    destHeight, PixelFormat.Format24bppRgb);
            bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                    imgPhoto.VerticalResolution);

            var grPhoto = Graphics.FromImage(bmPhoto);
            grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;

            grPhoto.DrawImage(imgPhoto,
                new Rectangle(destX, destY, destWidth + 1, destHeight + 1),
                new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
                GraphicsUnit.Pixel);

            grPhoto.Dispose();

            return bmPhoto;
        }

        public static void BindAndHideIfNoItems(this Repeater repeater, IEnumerable items, int itemsCount)
        {
            if (itemsCount > 0)
            {
                repeater.Visible = true;
                repeater.DataSource = items;
                repeater.DataBind();
            }
            else
            {
                repeater.Visible = false;
            }
        }

        public static void BindAndHideIfNoItems(this Repeater repeater, IList items)
        {
            repeater.BindAndHideIfNoItems(items, items.Count);
        }

        public static IEnumerable<string> GetCheckedValues(this CheckBoxList list)
        {
            var items = new List<string>();
            foreach (ListItem item in list.Items)
            {
                if (item.Selected)
                    items.Add(item.Value);
            }
            return items.AsEnumerable();
        }

        public static IEnumerable<ListItem> AddDefaultItem(this IEnumerable<ListItem> items)
        {
            return items.AddDefaultItem("", "");
        }
        public static IEnumerable<ListItem> AddDefaultItem(this IEnumerable<ListItem> items,
            string defaultValue, string defaultText)
        {
            return new[] { new ListItem { Text = defaultText, Value = defaultValue } }
                    .Union(items);
        }
    }
}